<template>
  <template v-for="(tag, index) in value" :key="index">
    <Tooltip v-if="tag.length > omitLength" :title="tag">
      <Tag
        v-bind="$attrs"
        :key="tag"
        :closable="index >= 0 && editEnabled === true"
        :color="getTagColor()"
        @close="handleTagRemove(value, tag)"
      >
        {{ `${tag.slice(0, omitLength)}...` }}
      </Tag>
    </Tooltip>
    <Tag
      v-bind="$attrs"
      :key="tag"
      v-else
      :closable="index >= 0 && editEnabled === true"
      :color="getTagColor()"
      @close="handleTagRemove(value, tag)"
    >
      {{ tag }}
    </Tag>
  </template>
  <Input
    v-bind="$attrs"
    v-if="tagInputVisible === true && editEnabled === true"
    ref="tagInputRef"
    type="text"
    size="small"
    :style="{ width: '78px' }"
    v-model:value="tagInputValue"
    @blur="handleTagInputConfirm(value)"
    @keyup.enter="handleTagInputConfirm(value)"
  />
  <Tag
    v-bind="$attrs"
    v-else-if="tagInputVisible === false && editEnabled === true"
    @click="showTagInput"
    style="border-style: dashed"
  >
    <Icon icon="ant-design:plus-outlined" /> {{ addTagText }}
  </Tag>
</template>
<script lang="ts">
  import { defineComponent, ref, reactive, toRefs, nextTick, PropType, watch } from 'vue';
  import { Tooltip, Tag, Input } from 'ant-design-vue';
  import Icon from '@/components/Icon/Icon.vue';
  import { propTypes } from '@/utils/propTypes';

  import { isFunction } from '@/utils/is';

  const props = {
    /** 绑定值 */
    value: {
      type: [Array] as PropType<string[]>,
      default: () => [],
    },
    /** 超出省略字符长度 */
    omitLength: propTypes.number.def(20),
    /** 启用编辑 */
    editEnabled: propTypes.bool.def(true),
    /** 随机色 */
    randomColor: propTypes.bool.def(false),
    /** 增加标签按钮显示文本 */
    addTagText: propTypes.string.def('New Tag'),
    /** 标签增加前回调，返回true增加标签 */
    beforeTagAddFunc: {
      type: Function as PropType<(tags: string[], addedTag: string) => Promise<boolean>>,
      default: null,
    },
    /** 标签删除前回调，返回true移除标签 */
    beforeTagRemoveFunc: {
      type: Function as PropType<(tags: string[], removedTag: string) => Promise<boolean>>,
      default: null,
    },
  };

  export default defineComponent({
    name: 'TagEditor',
    components: { Tooltip, Tag, Input, Icon },
    props,
    emits: ['change'],
    setup(props, { emit }) {
      const tagInputRef = ref();
      const tagState = reactive({
        tagValue: props.value,
        tagInputVisible: false,
        tagInputValue: '',
      });
      const tagDefColor = 'default';
      const tagColors = [
        'magenta',
        'pink',
        'red',
        'volcano',
        'orange',
        'gold',
        'lime',
        'green',
        'cyan',
        'blue',
        'geekblue',
        'purple',
      ];

      // watch在监听 reactive类型
      watch(
        () => tagState.tagValue,
        (newValue, _oldValue) => {
          // console.log('old', oldValue);
          // console.log('new', newValue);
          emit('change', newValue);
        },
      );

      /** 获取标签颜色 */
      function getTagColor(): string {
        const { randomColor } = props;
        // console.log('randomColor', randomColor);
        if (randomColor === false) {
          return tagDefColor;
        }
        var index = Math.floor(Math.random() * tagColors.length);
        // console.log('newColor', tagColors[index]);
        return tagColors[index];
      }

      /** 处理标签移除 */
      async function handleTagRemove(tags: string[], removedTag: string) {
        const { beforeTagRemoveFunc } = props;
        let canRemove = true;
        if (beforeTagRemoveFunc && isFunction(beforeTagRemoveFunc)) {
          canRemove = await beforeTagRemoveFunc(tags, removedTag);
        }
        if (canRemove === true) {
          tags = tags.filter((tag: string) => tag !== removedTag);
          // console.log(tagState.tagValue);
          if (tagState.tagValue !== tags) {
            tagState.tagValue = tags;
          }
          // emit('change', tagState.tagValue);
        }
      }
      /** 显示标签输入框 */
      function showTagInput() {
        tagState.tagInputVisible = true;
        nextTick(() => {
          tagInputRef.value.focus();
        });
      }
      /** 处理标签输入确认 */
      async function handleTagInputConfirm(tags: string[]) {
        const inputValue = tagState.tagInputValue;
        if (inputValue) {
          const { beforeTagAddFunc } = props;
          let canAdd = true;
          if (beforeTagAddFunc && isFunction(beforeTagAddFunc)) {
            canAdd = await beforeTagAddFunc(tags, inputValue);
          }
          if (canAdd === true) {
            if (tags === undefined || tags === null || tags.length <= 0) {
              tags = [inputValue];
            } else if (tags.indexOf(inputValue) === -1) {
              tags = [...tags, inputValue];
            }
          }
        }
        Object.assign(tagState, {
          tagInputVisible: false,
          tagInputValue: '',
        });
        // console.log('tags', tags);
        // console.log('inputTag', inputValue);
        if (tagState.tagValue !== tags) {
          tagState.tagValue = tags;
        }
        // emit('change', tagState.tagValue);
      }

      return {
        tagInputRef,
        ...toRefs(tagState),
        getTagColor,
        handleTagRemove,
        showTagInput,
        handleTagInputConfirm,
      };
    },
  });
</script>
